#include <errno.h>
#include <cstring>
#include <string>
#include <cstdio>
#include <cassert>
#include <sys/types.h>
#include <sys/wait.h>
#include "ctrlproc.hpp"

const size_t TaskNum = 3;

class Task //进程对象
{
public:
    Task(pid_t id,int fd)
        :_id(id)
        ,_writefd(fd)
    {}
    ~Task(){}
public:
    pid_t _id;
    int _writefd;
};

// void clear() //清屏功能
// {
//     int id = fork();
//     assert(id != -1);
//     if(id == 0)
//     {
//         execlp("clear",NULL);
//     }
// }

void WaitCommand()//执行流
{
    while(true)
    {
        int command = 0;
        int n = read(0,&command,4);//读取四字节指令
        if(n == -1)
        {
            cerr<<"read error"<<endl;
            break;
        }
        else if(n == sizeof(int))
        {
            cout<<"进程"<<getpid();
            Func()(command);
        }
        else
        {
            break;
        }
    }
}

void CreatTask(vector<Task>& t)
{
    vector<int> nfd;
    for(int i = 0;i<TaskNum;++i)
    {
        //开通管道
        int fd[2] = {0};
        int n = pipe(fd);
        assert(n != -1);

        //创建子进程
        pid_t id = fork();
        assert(id != -1);
        if(id == 0)
        {
            //子进程
            for(auto& d:nfd) close(d); //关闭冗余的fd
            close(fd[1]); //关闭写
            dup2(fd[0],0); //重定向读取端到标准输出
            //执行流
            WaitCommand();
            close(fd[0]);
            exit(0);
        }

        //父进程
        close(fd[0]); //关闭读
        t.push_back(Task(id,fd[1])); //写入进程对象
        nfd.push_back(fd[1]); //写入父进程冗余的fd防止被其他子进程继承
    }
}

int menu()
{
    cout<<"**********************************"<<endl;
    cout<<"*0.执行日志任务  1.执行数据库任务*"<<endl;
    cout<<"*2.执行网络任务  3.退出          *"<<endl;
    cout<<"**********************************"<<endl;
    cout<<"请选择> ";
    int input = 0;
    cin >> input;
    cout<<endl;
    return input;

}

void clean(const vector<Task>& t)
{
    for(const auto& n:t)
    {
        close(n._writefd); //关闭写端
        cout<<"子进程"<<n._id<<"退出"<<endl;
        waitpid(n._id,NULL,0);
        cout<<"子进程"<<n._id<<"被回收"<<endl;
    }
}

void ExecProc(const vector<Task>& t)
{
    int num = 0;
    //分配任务
    while(true)
    {
        int command = menu(); //选择任务
        if(command < 0 && command > 3) {continue;}
        if(command == 3) break;
        write(t[num]._writefd,&command,sizeof(int));
        ++num;
        num %= 3;
        sleep(1);
    }
}

int main()
{
    //实现父进程与多个子课程进行通信
    vector<Task> t;

    //模块化

    CreatTask(t); //创建TaskNum个进程池

    ExecProc(t); //执行任务

    clean(t); //执行清理任务
    return 0;
}

